# -*- coding: utf-8 -*-
import PySimpleGUI as sg
import os
import cv2 as cv
import numpy as np

def img2blackwhite(img):
    # 二值化
    # th3 = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 19, 3)
    th3 = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 31, 9)
    return th3

def contrast_brightness_image(srcimg, a=1.2, g=10):
    # a: 对比度， g：亮度
    h, w = srcimg.shape
    src2 = np.zeros([h, w], srcimg.dtype)
    dst = cv.addWeighted(srcimg, a, src2, 1-a, g)
    return dst

def color_scale_display(img, Shadow=70, Highlight=180, Midtones=1):
    # 调整色阶
    if Highlight > 255:
        Highlight = 255
    if Shadow < 0:
        Shadow = 0
    if Shadow >= Highlight:
        Shadow = Highlight - 2
    if Midtones > 9.99:
        Midtones = 9.99
    if Midtones < 0.01:
        Midtones = 0.01
    # 转类型
    img = np.array(img, dtype=np.float16)
    # 计算白场黑场离差
    Diff = Highlight - Shadow
    img = img - Shadow
    img[img < 0] = 0
    img = (img/Diff)**(1/Midtones)*255
    img[img > 255] = 255
    # 转类型
    img = np.array(img, dtype=np.uint8)
    return img

def handle_pic(mode='WORK', imgFile='', srcDir='', destDir='', contrast=True, scale=True, bw=False, contrast_value=1.2,
               bright_value=10, scaleS_value=70, scaleH_value=180):
    if not imgFile or not srcDir or not destDir:
        return None
    res = None
    (fname, ext) = os.path.splitext(imgFile)
    if ext.lower() == '.jpg' or ext.lower() == '.png':
        try:
            # img = cv.imread(os.path.join(srcDir, file), 0)
            srcimg = cv.imdecode(np.fromfile(os.path.join(srcDir, imgFile), dtype=np.uint8), 0)  # 解决中文路径读取问题
            img = srcimg
            if contrast:
                img = contrast_brightness_image(img, contrast_value, bright_value)
            if scale:
                img = color_scale_display(img, scaleS_value, scaleH_value)
            if bw:
                img = img2blackwhite(img)
            if mode == 'WORK':   # 转换模式
                outFile = os.path.join(destDir, fname + '_1' + ext)
                cv.imencode(ext, img)[1].tofile(str(outFile))  # 解决中文路径保存问题
                # cv.imwrite(str(outFile), img)
                res = 1
            else:    # 预览模式
                destimg = cv.hconcat((srcimg, img))  # 拼接原始图和调整图
                cv.namedWindow("imagewin", 0);
                cv.resizeWindow("imagewin", 1200, 800);
                cv.imshow("imagewin", destimg)
                while cv.waitKey(100) != 27:  # 检测按键 ESC 退出
                    if cv.getWindowProperty('imagewin', cv.WND_PROP_VISIBLE) <= 0:    # 检测窗口属性，关闭窗口后非visible退出循环
                        break
                cv.destroyWindow('imagewin')
                res = 1
        except:
            pass
    return res


def run_window():
    label1_1 = sg.Text("  源 文件夹")
    label1_2 = sg.Text("目标文件夹")
    srcdir = sg.InputText(size=(40, 20))
    destdir = sg.InputText(size=(40, 20))
    src_browser = sg.FolderBrowse('浏览', key='SrcDir')
    dest_browser = sg.FolderBrowse('浏览', key='DestDir')
    lbcontrast = sg.Text('对比度')
    slidbar1 = sg.Slider(range=(0, 5), default_value=1.2, resolution=0.1, orientation='h', size=(32, 20), key='contrast')
    lbbright = sg.Text('亮  度')
    slidbar2 = sg.Slider(range=(0, 50), default_value=10, orientation='h', size=(32, 20), key='bright')
    lbscales = sg.Text('色阶黑场')
    slidbar4 = sg.Slider(range=(0, 255), default_value=70, orientation='h', size=(30, 20), key='scales')
    lbscaleh = sg.Text('色阶白场')
    slidbar5 = sg.Slider(range=(0, 255), default_value=180, orientation='h', size=(30, 20), key='scaleh')
    check1 = sg.Checkbox('亮度和对比度',default=True,key='chk_contrast',enable_events=True)
    check2 = sg.Checkbox('色阶',default=True,key='chk_scale',enable_events=True)
    check3 = sg.Checkbox('二值化',default=False,key='chk_bw')
    label3 = sg.Text("当前进度")
    progressbar = sg.ProgressBar(1000, orientation='h', size=(32, 20), key='progbar')
    ok_btn = sg.Button('确定')
    preview_btn = sg.Button('预览')
    cancel_btn = sg.Button('退出')
    # 构造窗体
    layout = [[label1_1, srcdir, src_browser],
              [label1_2, destdir, dest_browser],
              [lbcontrast, slidbar1],
              [lbbright, slidbar2],
              [lbscales, slidbar4],
              [lbscaleh, slidbar5],
              [check1, check2, check3],
              [label3, progressbar], [ok_btn, preview_btn, cancel_btn]]
    window = sg.Window('作业图片批量转换', layout)

    # Create the event loop
    while True:
        event, values = window.read(timeout=100)
        if event in (None, '退出'):
            # User closed the Window or hit the Cancel button
            break
        if event == sg.TIMEOUT_KEY:
            # print('Nothing happened')
            pass
        elif event == 'chk_contrast':
            window['contrast'].update(disabled=not values['chk_contrast'])
            window['bright'].update(disabled=not values['chk_contrast'])
        elif event == 'chk_scale':
            window['scales'].update(disabled=not values['chk_scale'])
            window['scaleh'].update(disabled=not values['chk_scale'])
        elif event == '预览' and values['SrcDir']:
            baseDir = os.path.abspath(values['SrcDir'])
            destDir = os.path.abspath(values['DestDir'])
            files = os.listdir(baseDir)
            for file in files:
                if handle_pic('PREVIEW', file, baseDir, destDir, values['chk_contrast'], values['chk_scale'], values['chk_bw'],
                              values['contrast'], values['bright'], values['scales'], values['scaleh']):
                    break
        elif event == '确定' and values['SrcDir'] and values['DestDir']:
            window.Element('progbar').UpdateBar(0)
            srcDir = os.path.abspath(values['SrcDir'])
            destDir = os.path.abspath(values['DestDir'])
            files = os.listdir(srcDir)
            totalFiles = len(os.listdir(srcDir))
            finishFiles = 0
            for file in files:
                handle_pic('WORK', file, srcDir, destDir, values['chk_contrast'], values['chk_scale'], values['chk_bw'],
                           values['contrast'], values['bright'], values['scales'], values['scaleh'])
                finishFiles += 1
                window.Element('progbar').UpdateBar(int(finishFiles*1000/totalFiles))
            sg.popup_ok('转换工作完成!')
        else:
            sg.popup_ok('请选择原始图片目录和导出图片目录!')

    window.close()

if __name__ == '__main__':
    run_window()
